

class MyPromise {
  state = "pending";  // 三种状态：pending fulfilled rejected
  value = undefined; // 终值，成功的结果
  reason = undefined; // 拒因，失败的结果

  resolveCallbacks = []; // pending状态下，存储成功的回调
  rejectCallbacks = []; // pending状态下，存储失败的回调

  constructor(fn) {
    const resolveHeander = (value) => {
      if (this.state === 'pending') {
        this.state = 'fulfilled'
        this.value = value;
        this.resolveCallbacks.forEach(fn => fn(this.value))
      }
    }
    const rejectHeander = (reason) => {
      if (this.state === 'pending') {
        this.state = 'rejected'
        this.reason = reason;
        this.rejectCallbacks.forEach(fn => fn(this.reason))
      }
    }

    try {
      fn(resolveHeander, rejectHeander)
    } catch (err) {
      rejectHeander(err)
    }
  }

  // 当pending状态下，需要把fn1,fn2存储到Callbacks
  // then的返回值是一个新的promise
  then(fn1, fn2) {
    fn1 = typeof fn1 === 'function' ? fn1 : (v) => v
    fn2 = typeof fn2 === 'function' ? fn2 : (e) => e

    if (this.state === 'pending') {
      const p1 = new MyPromise((resolve, reject) => {
        this.resolveCallbacks.push(() => {
          try {
            const newValue = fn1(this.value);
            resolve(newValue)
          } catch (err) {
            reject(err)
          }
        })
        this.rejectCallbacks.push(() => {
          try {
            const newReason = fn2(this.reason);
            reject(newReason)
          } catch (err) {
            reject(err)
          }
        })
      })
      return p1;
    }
    if (this.state === 'fulfilled') {
      const p1 = new MyPromise((resolve, reject) => {
        try {
          const newValue = fn1(this.value)
          resolve(newValue)
        } catch (err) {
          reject(err)
        }
      })
      return p1;
    }
    if (this.state === 'rejected') {
      const p1 = new MyPromise((resolve, reject) => {
        try {
          const newReason = fn2(this.reason)
          reject(newReason)
        } catch (err) {
          reject(err)
        }
      })
      return p1;
    }
  }

  // catch仅仅是then的语法糖
  catch(fn) {
    return this.then(null, fn)
  }
}

MyPromise.resolve = function (value) {
  return new MyPromise((resolve, reject) => resolve(value))
}

MyPromise.reject = function (reason) {
  return new MyPromise((resolve, reject) => reject(reason))
}

MyPromise.all = function (promiseList = []) {
  let p1 = new MyPromise((resolve, reject) => {
    const result = []; // 存储promisList所有的结果
    const length = promiseList.length;
    let resolvedCount = 0;

    promiseList.forEach(p => {
      p.then(data => {
        result.push(data)
        resolvedCount++;
        if (resolvedCount === length) {
          // 已经遍历到最后一个Promise
          resolve(result)
        }
      }).catch(err => {
        reject(err)
      })
    })
  })

  return p1;
}

MyPromise.race = function (promiseList = []) {
  let resolved = false; // 标记
  let p1 = new MyPromise((resolve, reject) => {
    promiseList.forEach(p => {
      p.then(data => {
        if (!resolved) {
          resolve(data)
          resolved = true;
        }
      }).catch(err => {
        reject(err)
      })
    })
  })

  return p1;
}